package io.bdmc.core.snmp;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import io.bdmc.common.exception.FileLengthNotEnoughException;
import io.bdmc.common.utils.*;
import io.bdmc.core.snmp.cache.ConcurrentHashMapCacheUtils;
import io.bdmc.modules.bss.entity.*;
import io.bdmc.modules.bss.model.SorEvent;
import io.bdmc.modules.bss.model.SorFileParser;
import io.bdmc.modules.bss.service.*;
import io.bdmc.modules.sys.entity.SysAbout;
import io.bdmc.modules.sys.service.ISysAboutService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;

@Component
public class SnmpTrapThreadPool {

    private static final Logger logger = LoggerFactory.getLogger((SnmpTrapThreadPool.class));

    @Autowired
    IDeviceDeviceService _devSvs;

    @Autowired
    MultiThreadedTrapReceiver _trapReceiver;

    @Autowired
    IDeviceStatusStaticService _dssSvs;

    @Autowired
    IDeviceMonitorDynamicService _dmcSvs;

    @Autowired
    IDeviceMeasureService _measureSvs;

    @Autowired
    IDeviceMeasureEventService _measureEventSvs;

    @Autowired
    IDeviceAlarmSettingService _devAlarmSettingSvs;

    @Autowired
    SnmpAlarmProcess alarmProcess;

    @Autowired
    IDeviceFibreRealtimeService _dfrSvs;

    @Autowired
    ISysAboutService _aboutSvs;

    @Autowired
    SMSUtils smsUtils;

    int staticCount = 0;
    int dynamicCount = 0;

    /**
     * 启动udp线程监听snmp设备，异步接收trap数据
     */
    @Async
    public void startUpUdp() {
        for (String ip : Objects.requireNonNull(CommonUtil.getInet4Address())) {
            _trapReceiver.run(ip);
        }
    }

    // Thread.currentThread().getName()
    /**
     * 启动智能测试
     */
    @Async
    public void startIntelligentTesting() {
        logger.info(Thread.currentThread().getName() + "startIntelligentTesting");
        // SnmpDataCache.setIntelligentTestThreadStatus(true);
        // List<String> _intelligentTestList = SnmpDataCache.getIntelligentTestList();
        // HashMap<String, DeviceMeasure> measureNowMap =
        // SnmpDataCache.getMeasureNowMap();
        // while (_intelligentTestList.size() > 0) {
        // for (String ipaddrChannel : _intelligentTestList) {
        // String[] arr = ipaddrChannel.split(",");
        // QueryWrapper<DeviceMeasure> w1 = new
        // QueryWrapper<DeviceMeasure>().eq("device_ip", arr[0])
        // .eq("channel", arr[1]).eq("standard", true).last("LIMIT 1");
        // ;
        // DeviceMeasure dm = _measureSvs.getOne(w1);
        // String nowTestKey = Constant.MeasureNowMapPrefix + ":" + dm.getDeviceIp() +
        // ":"
        // + Constant.ACTION_ManualTest + ":" + dm.getChannel();
        // // 查看是否正在进行测试，如果结束后才启动下一次手动测试
        // if (ConcurrentHashMapCacheUtils.isExist(nowTestKey)) {
        // continue;
        // }

        // Integer endPostion = dm.getEndPosition();
        // // 判断上一次的量程
        // DeviceMeasure m = _measureSvs
        // .getOne(new QueryWrapper<DeviceMeasure>().eq("device_ip",
        // arr[0]).eq("channel", arr[1])
        // .eq("action", 3).eq("measure_status",
        // 3).orderByDesc("measure_id").last("LIMIT 1"));
        // if (m != null) {
        // DeviceMeasureEvent dv = _measureEventSvs.getOne(new
        // QueryWrapper<DeviceMeasureEvent>()
        // .eq("measure_id", m.getMeasureId()).eq("event_type", "光纤终端").last("LIMIT
        // 1"));
        // if (dv != null && dv.getEventPropagationDistance().compareTo(new
        // BigDecimal("5")) < 0) {
        // endPostion = 5;
        // }
        // }

        // boolean sendResult = SnmpData.setSigleMeasure(arr[0], dm.getChannel(), 3,
        // String.valueOf(endPostion),
        // String.valueOf(dm.getRefIndex()), String.valueOf(dm.getResolution()),
        // String.valueOf(dm.getPulseWidth()), dm.getDuration());
        // LocalDateTime now = LocalDateTime.now();
        // if (sendResult) {
        // DeviceMeasure measure = new
        // DeviceMeasure().setAverageNum(1).setDeviceId(dm.getDeviceId())
        // .setDeviceIp(arr[0]).setStandard(false).setDeptId(dm.getDeptId())
        // .setChannel(dm.getChannel()).setAction(dm.getAction()).setEndPosition(endPostion)
        // .setPulseWidth(dm.getPulseWidth()).setMeasureStatus(2).setStartTime(now)
        // .setDuration(dm.getDuration()).setResolution(dm.getResolution())
        // .setRefIndex(dm.getRefIndex()).setCreateBy(dm.getCreateBy()).setCreateTime(now);
        // measure.insert();
        // // 缓存本次测试

        // String key = Constant.MeasureNowMapPrefix + ":" + dm.getDeviceIp() + ":"
        // + Constant.ACTION_ManualTest + ":" + dm.getChannel();
        // ConcurrentHashMapCacheUtils.setCache(key, measure);
        // }
        // }
        // try {
        // Thread.sleep(5000);
        // } catch (InterruptedException e) {
        // e.printStackTrace();
        // }
        // }
        // SnmpDataCache.setIntelligentTestThreadStatus(false);
    }

    /**
     * 解析snmp的trap 数据到数据库
     */
    @Async
    public void customerSnmpData() {
        logger.info(Thread.currentThread().getName() + "----trap start");
        while (true) {
            try {
                boolean emptyQueue = SnmpDataCache.isEmptyTrapQueue();
                if (!emptyQueue) {
                    final String str = SnmpDataCache.pollTrapQueue();
                    final String[] args = str.split(",");
                    final QueryWrapper<DeviceDevice> w1 = new QueryWrapper<>();
                    w1.eq("ipaddr", args[0]).last("LIMIT 1");
                    final DeviceDevice dev = _devSvs.getOne(w1);

                    if (dev != null) {
                        alarmProcess.receiveTrapAlarm(str, dev.getDeptId(), dev.getDeviceId(), dev.getDeviceSn());
                    }
                }
                Thread.sleep(3000);
            } catch (final Exception e) {
                e.printStackTrace();
                logger.error(e.toString());
            }
        }
    }

    /**
     * 自动删除测量数据的任务，同时删除测量文件
     */
    @Scheduled(cron = "0 0 0/1 * * ? ")
    public void startMeasureRemoveThread() {
        logger.info(Thread.currentThread().getName() + "---startMeasureRemoveThread");
        try {
            SysAbout about = _aboutSvs.getOne(new QueryWrapper<SysAbout>().last("LIMIT 1"));
            int day = about.getMeasureSaveTime();
            if (day > 0) {
                String deleteDateTime = DateUtils.formatLocalDateTimeDefault(LocalDateTime.now().minusDays((long) day));
                QueryWrapper<DeviceMeasure> w1 = new QueryWrapper<DeviceMeasure>().le("end_time", deleteDateTime);
                w1.and(i -> i.isNull("standard").or().ne("standard", 1));
                List<DeviceMeasure> list = _measureSvs.list(w1);
                for (DeviceMeasure deviceMeasure : list) {
                    String sorPath = deviceMeasure.getSorPath();
                    FTPUtils.deleteFile(sorPath);
                }
                _measureSvs.remove(w1);
                logger.info(Thread.currentThread().getName() + "测量记录删除成功--" + list.size());
            }
        } catch (Exception e) {
            logger.error(e.toString());
        }
    }

    /**
     * 启动静态数据定时任务
     */
    @Scheduled(fixedDelay = 1000 * 3)
    public void startStaticStatusRead() {
        // System.out.println("********静态数据读取任务启动*********");
        try {
            final List<DeviceDevice> list = _devSvs.getByDigestAndType(Constant.IFMS1000, Constant.IFMS1000);
            for (final DeviceDevice device : list) {
                final DeviceStatusStatic dss = SnmpData.snmpAsyncWalkStatusStatic(device.getIpaddr(),
                        device.getReadCode());
                if (dss == null || StringUtils.isEmpty(dss.getDevIpAddr())) {
                    // System.out.println("********DeviceStatusStatic 获取的数据或ip是空********");
                    continue;
                }
                // 设备读取的数据没有deviceid 每次需要赋值
                dss.setDeviceId(device.getDeviceId());
                long dbDss = _dssSvs
                        .count(new QueryWrapper<DeviceStatusStatic>().eq("dev_ip_addr", dss.getDevIpAddr()));
                if (dbDss > 0) {
                    // 数据库存在该设备的静态数据就更新
                    final Wrapper<DeviceStatusStatic> w1 = new UpdateWrapper<DeviceStatusStatic>().eq("dev_ip_addr",
                            dss.getDevIpAddr());
                    _dssSvs.update(dss, w1);
                } else {
                    dss.insert();
                }
                // 更新缓存
                ConcurrentHashMapCacheUtils.setCache(Constant.DeviceStatusStaticPrefix + dss.getDevIpAddr(), dss);
                // 更新设备的sn 和 mac
                device.setDeviceSn(dss.getPstSn());
                device.setDeviceMac(dss.getDevMacAddress());
                device.updateById();
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 启动动态数据定时任务
     */
    @Scheduled(fixedDelay = 1000 * 3)
    public void startDynamicStatusRead() {
        final List<DeviceDevice> devList = _devSvs.listByType(Constant.IFMS1000);
        for (final DeviceDevice device : devList) {
            final DeviceMonitorDynamic dmc = SnmpData.snmpAsyncWalkMonitorDynamic(device.getIpaddr(),
                    device.getReadCode());
            if (dmc == null || dmc.getStatus() == null) {
                continue;
            }
            dmc.setDeviceId(device.getDeviceId());
            // 拿缓存的上一次的数据
            final DeviceMonitorDynamic temp = (DeviceMonitorDynamic) ConcurrentHashMapCacheUtils
                    .getCache(Constant.DeviceMonitorDynamicPrefix + ":" + dmc.getDevIpAddr());
            // 更新缓存中的数据
            ConcurrentHashMapCacheUtils.setCache(Constant.DeviceMonitorDynamicPrefix + ":" + dmc.getDevIpAddr(), dmc);
            // 修改数据库
            _dmcSvs.remove(new QueryWrapper<DeviceMonitorDynamic>().eq("device_id", dmc.getDeviceId()).ne("dev_ip_addr",
                    device.getIpaddr()));
            if (_dmcSvs.count(new QueryWrapper<DeviceMonitorDynamic>().eq("dev_ip_addr", device.getIpaddr())) > 0) {
                final Wrapper<DeviceMonitorDynamic> w1 = new UpdateWrapper<DeviceMonitorDynamic>().eq("dev_ip_addr",
                        device.getIpaddr());
                _dmcSvs.update(dmc, w1);
            } else {
                dmc.insert();
            }

            final String[] statusArr = dmc.getStatus().split(",");
            final String[] portActive = dmc.getPortActive().split(",");

            // 遍历通道号
            for (int i = 0; i < portActive.length; i++) {
                int channel = i + 1;
                String autoKey = Constant.MeasureNowMapPrefix + ":" + device.getIpaddr() + ":"
                        + Constant.ACTION_AutoTest + ":" + channel;
                if (ConcurrentHashMapCacheUtils.getCache(autoKey) != null && statusArr[i].equals("0")) {
                    // 下发启动测试
                    SnmpData.setSingleMeasure(device.getIpaddr(), channel, 1, device.getWriteCode());
                }

                if (portActive[i].equals("0")) {// 通道未接光纤
                    continue;
                }
                DeviceMeasure measure = getNowTestingDeviceMeasure(channel, dmc.getAction().split(",")[i],
                        dmc.getDevIpAddr());

                if (measure != null && temp != null) {
                    // 手动测试,当前状态=已完成，缓存状态等于正在测试，说明刚刚测试完成，此时有可能下载的ftp未写完。
                    if (statusArr[i].equals("3") && temp.getStatus().split(",")[i].equals("2")) {
                        // 需要下载ftp文件
                        final String filePath = downloadFtpSor(dmc.getDevIpAddr(), channel, measure.getAction(),
                                device.getDeviceSn());
                        if (StringUtils.isEmpty(filePath)) {
                            continue;
                        }
                        measure.setSorPath(filePath);
                        measure.setMeasureStatus(3);
                        SorFileParser sor;
                        try {
                            sor = SORFileParserTool.parserSorFile(filePath);
                        } catch (final FileLengthNotEnoughException e) {
                            System.out.println(e);
                            break;
                        }
                        insertOrUpdateMeasureAndEvent(sor, measure, device.getDeviceType());
                        // 手动测试完成，需要更新缓存中的实时数据
                        updateDeviceFibreRealtime(dmc.getDevIpAddr(), channel, measure.getLength().toString(),
                                measure.getPadControl().toString());
                        // 测试完成，移除缓存中的测试key
                        final String manualMeasureKey = Constant.MeasureNowMapPrefix + ":" + dmc.getDevIpAddr() + ":"
                                + Constant.ACTION_ManualTest + ":" + channel;
                        ConcurrentHashMapCacheUtils.deleteCache(manualMeasureKey);
                    } else if (statusArr[i].equals("1") && temp.getStatus().split(",")[i].equals("1")) {
                        // 自动测试, 当前progress_status<上一次当前progress_status,代表一次测试完成，插入measure
                        final int now_progress_status = Integer.parseInt(dmc.getProgressStatus().split(",")[i]);
                        final int temp_progress_status = Integer.parseInt(temp.getProgressStatus().split(",")[i]);
                        if (now_progress_status < temp_progress_status) {
                            // 需要下载ftp文件
                            final String filePath = downloadFtpSor(dmc.getDevIpAddr(), channel, measure.getAction(),
                                    device.getDeviceSn());
                            if (StringUtils.isEmpty(filePath)) {
                                continue;
                            }
                            final DeviceMeasure m1 = measure.clone();
                            m1.setAutoTaskNum(measure.getAutoTaskNum());
                            m1.setAutoTaskCount(Integer.valueOf(dmc.getNumber().split(",")[i]));
                            m1.setSorPath(filePath);
                            m1.setMeasureStatus(5);
                            m1.setEndTime(LocalDateTime.now());
                            m1.setCreateTime(LocalDateTime.now());
                            SorFileParser sor = null;
                            try {
                                sor = SORFileParserTool.parserSorFile(filePath);
                            } catch (final FileLengthNotEnoughException e) {
                                System.out.println(e.getMessage());
                                break;
                                // 文件长度不够，需要等待下一次的读取再解析
                            }
                            insertOrUpdateMeasureAndEvent(sor, m1, device.getDeviceType());
                            // 更新缓存中的实时数据
                            updateDeviceFibreRealtime(dmc.getDevIpAddr(), channel, m1.getLength().toString(),
                                    m1.getPadControl().toString());
                            // 判断衰耗报警
                        }
                    }
                }
            }

        }
        // System.out.println("---------动态数据读取全部完成---------");
    }

    @Scheduled(fixedDelay = 1000 * 30)
    public void startSendSms() {
        boolean isempty = SnmpDataCache.isEmptySmsQueue();
        if (!isempty) {
            SnmpSMSData smsData = SnmpDataCache.pollSmsQueue();
            Boolean sendResult = smsUtils.sendSMSLong(smsData.getIpAddr(), smsData.getPort(), smsData.getMobile(),
                    smsData.getMessage());
            logger.info("给" + smsData.getMobile() + "发送短信结果：" + sendResult + "》》》" + smsData.getMessage());
        }

    }

    /**
     * 更新每个通道测量的实时信息
     * 
     * @param ipAddr      ip
     * @param channel     端口
     * @param fibreLength 光纤长度
     * @param fibreLoss   衰耗
     */
    private void updateDeviceFibreRealtime(String ipAddr, int channel, String fibreLength, String fibreLoss) {
        // 更新缓存
        ConcurrentHashMapCacheUtils.setCache(Constant.DeviceChannelRealtimePrefix + ipAddr + ":" + channel,
                fibreLength + "," + fibreLoss);
        // 更新数据库
        QueryWrapper<DeviceFibreRealtime> w1 = new QueryWrapper<DeviceFibreRealtime>();
        w1.eq("ip_addr", ipAddr).eq("channel", channel).last(" LIMIT 1");
        DeviceFibreRealtime dfr = _dfrSvs.getOne(w1);
        if (dfr == null) {
            dfr = new DeviceFibreRealtime();
            dfr.setIpAddr(ipAddr);
            dfr.setChannel(channel);
            dfr.setFibreLength(fibreLength);
            dfr.setFibreLoss(fibreLoss);
            dfr.setCreateTime(LocalDateTime.now());
            dfr.insert();
        } else {
            dfr.setFibreLength(fibreLength);
            dfr.setFibreLoss(fibreLoss);
            dfr.setCreateTime(LocalDateTime.now());
            dfr.updateById();
        }

    }

    /**
     * 获取当前正在进行的测量信息
     */
    private DeviceMeasure getNowTestingDeviceMeasure(int channel, String action, String ipAddr) {
        DeviceMeasure measure = null;
        final String autoMeasureKey = Constant.MeasureNowMapPrefix + ":" + ipAddr + ":" + 1 + ":" + +channel;
        final String manualMeasureKey = Constant.MeasureNowMapPrefix + ":" + ipAddr + ":" + 3 + ":" + +channel;
        // 查询当前正在单次测试的通道
        if (ConcurrentHashMapCacheUtils.isExist(autoMeasureKey)) {
            measure = (DeviceMeasure) ConcurrentHashMapCacheUtils.getCache(autoMeasureKey);
        } else if (ConcurrentHashMapCacheUtils.isExist(manualMeasureKey)) {
            measure = (DeviceMeasure) ConcurrentHashMapCacheUtils.getCache(manualMeasureKey);
        }

        // 缓存中没有 ，查看实际情况是不是再进行中，避免服务重启后出现这种情况
        if (measure == null) {
            QueryWrapper<DeviceMeasure> nowMeasure = new QueryWrapper<DeviceMeasure>();
            if (action.equals("3")) {
                // 设备状态正在手动测试
                nowMeasure.eq("device_ip", ipAddr).eq("action", action).ne("measure_status", 2).last("LIMIT 1")
                        .orderByDesc("measure_id");
                DeviceMeasure m = _measureSvs.getOne(nowMeasure);
                if (m != null) {
                    ConcurrentHashMapCacheUtils.setCache(manualMeasureKey, m);
                }
            }
            if (action.equals("1")) {
                // 设备状态正在自动测试
                nowMeasure.eq("device_ip", ipAddr).eq("action", action).ne("measure_status", 1).isNull("end_time")
                        .last("LIMIT 1").orderByDesc("measure_id");
                DeviceMeasure m = _measureSvs.getOne(nowMeasure);
                if (m != null) {
                    ConcurrentHashMapCacheUtils.setCache(autoMeasureKey, m);
                }
            }

        }
        return measure;
    }

    // 下载sor文件
    private String downloadFtpSor(final String ipaddr, final int channel, final int action, String deviceSn) {
        String path;
        if (StringUtils.isEmpty(deviceSn)) {
            deviceSn = "";
        }
        final DeviceStatusStatic statusStatic = (DeviceStatusStatic) ConcurrentHashMapCacheUtils
                .getCache(Constant.DeviceStatusStaticPrefix + ipaddr);
        String fileName = "";
        if (action == 1) {
            fileName = "IFMS_CH" + channel + "_SOR_Current.sor";
        } else if (action == 3) {
            fileName = "IFMS_CH" + channel + "_SOR_Single.sor";
        }
        logger.info(Thread.currentThread().getName() + "准备下载文件：" + fileName);
        path = FTPUtils.downFile("/ram/", fileName, deviceSn, ipaddr, statusStatic.getFtpUserName(),
                statusStatic.getFtpUserPwd());
        return path;
    }

    // 插入测量任务，和测量事件，如果自动测试 则新增一条测量任务
    public void insertOrUpdateMeasureAndEvent(final SorFileParser sor, final DeviceMeasure measure, String deviceType) {
        final LocalDateTime now = LocalDateTime.now();
        // 波长
        measure.setWavelength(new BigDecimal(sor.getActualWavelength()));
        // 平均话次数
        measure.setAverageNum(sor.getAveragesNum());

        measure.setEndTime(now);
        BigDecimal zero = new BigDecimal(0);
        // 长度
        Optional<SorEvent> ose = sor.getSorEvents().stream().filter(r -> r.getEventCode().contains("E")).findAny();
        if (ose.isPresent()) {
            try {
                SorEvent ev = ose.get();
                if (ev.getEventPropagationDistance().length() > 0) {
                    measure.setLength(new BigDecimal(ev.getEventPropagationDistance()));
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        } else {
            measure.setLength(zero);
        }

        // 衰耗
        final double eel = sor.getEnd2EndLoss();
        final String eelresult = String.format("%.3f", eel);
        measure.setPadControl(new BigDecimal(eelresult));
        // 平均衰耗系数
        if (measure.getLength().compareTo(zero) > 0) {
            BigDecimal padControlQuotiety = measure.getPadControl().divide(measure.getLength(), 3,
                    RoundingMode.HALF_UP);
            measure.setPadControlQuotiety(padControlQuotiety);
        } else {
            measure.setPadControlQuotiety(zero);
        }

        measure.setReturnLoss(new BigDecimal(sor.getOpticalReturnLoss()));
        if (deviceType.equals(Constant.IFMS1000)) {
            // 如果是老设备则执行原有逻辑，新设备直接更新本次测量
            if (measure.getAction().equals(1)) {// 自动测试
                measure.setMeasureId(null);
                measure.insert();
            } else if (measure.getAction().equals(3)) {// 手动测试
                measure.updateById();
            }
        } else {
            measure.updateById();
        }
        if (sor.getSorEvents().size() > 0) {
            DeviceMeasureEvent endEvent = null;// 终点
            final List<DeviceMeasureEvent> refEvent = new ArrayList<>();// 所有反射点
            final List<DeviceMeasureEvent> deList = new ArrayList<>();
            final List<SorEvent> events = sor.getSorEvents();
            for (final SorEvent event : events) {
                final String distanceStr = event.getEventPropagationDistance();
                final DeviceMeasureEvent dme = new DeviceMeasureEvent().setMeasureId(measure.getMeasureId())
                        .setEventPropagationDistance(new BigDecimal(distanceStr))
                        .setAttenuationCoefficient(BigDecimal.valueOf(event.getAttenuationCoefficientLeadInFiber()))
                        .setCreateTime(now).setEventNumber(event.getEventNumber()).setEventCode(event.getEventCode());
                if (event.getEventCode().contains("E")) {// 终端事件
                    dme.setEventType("光纤终端");
                    dme.setReflcetivity(new BigDecimal(event.getReflcetivity()));
                    endEvent = dme;
                } else if (event.getEventCode().startsWith("1F") || event.getEventCode().contains("R")) {// 反射事件
                    dme.setEventType("反射点");
                    dme.setEventLoss(new BigDecimal(event.getEventLoss()));
                    dme.setReflcetivity(new BigDecimal(event.getReflcetivity()));
                    dme.setEventPropagationDistance(new BigDecimal(event.getEventPropagationDistance()));
                    dme.setTotalLosses(new BigDecimal(event.getTotalLosses()));
                    refEvent.add(dme);

                } else if (event.getEventCode().startsWith("0F") || event.getEventCode().contains("N")) {
                    dme.setEventType("非反射点");
                    dme.setEventLoss(new BigDecimal(event.getEventLoss()));
                    dme.setEventPropagationDistance(new BigDecimal(event.getEventPropagationDistance()));
                    dme.setTotalLosses(new BigDecimal(event.getTotalLosses()));
                    refEvent.add(dme);
                }
            }
            // 计算总损耗
            if (refEvent.size() == 0 && endEvent != null) {
                endEvent.setTotalLosses(
                        endEvent.getEventPropagationDistance().multiply(endEvent.getAttenuationCoefficient()));
                deList.add(endEvent);
            } else {// 中间有折射点，需要计算
                refEvent.sort(Comparator.comparing(DeviceMeasureEvent::getEventNumber));
                for (int i = 0; i < refEvent.size(); i++) {
                    final DeviceMeasureEvent ev = refEvent.get(i);
                    BigDecimal distance;
                    if (i > 0) {
                        distance = ev.getEventPropagationDistance()
                                .subtract(refEvent.get(i - 1).getEventPropagationDistance());
                    } else {
                        distance = ev.getEventPropagationDistance();
                    }

                    final BigDecimal tloss = distance.multiply(ev.getAttenuationCoefficient())
                            .add(ev.getEventLoss().abs());
                    ev.setTotalLosses(tloss);
                    deList.add(ev);
                }
                if (endEvent != null) {
                    BigDecimal endLoss = endEvent.getEventPropagationDistance()
                            .subtract(refEvent.get(refEvent.size() - 1).getEventPropagationDistance())
                            .multiply(endEvent.getAttenuationCoefficient());
                    final BigDecimal refTotalLoss = refEvent.stream().map(DeviceMeasureEvent::getTotalLosses)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    endLoss = endLoss.add(refTotalLoss);
                    endEvent.setTotalLosses(endLoss);
                    deList.add(endEvent);
                }
            }
            deList.add(new DeviceMeasureEvent().setCreateTime(now).setEventNumber(0).setEventType("光纤始端")
                    .setMeasureId(measure.getMeasureId()));
            _measureEventSvs.saveBatch(deList);
        }
    }

}
